<template>
  <a-card :bordered='false'>
    <div id='project-plan-document'></div>
  </a-card>
</template>

<script>
import { getAction } from '@api/manage'
import HfElevatorLayer from '@/views/hifar/components/HfElevatorLayer'
import * as echarts from 'echarts'
import { filterDictTextByCache } from '@comp/dict/JDictSelectUtil'


export default {
  name: 'HfPmWorkReportsStatistics',
  components: { HfElevatorLayer },
  inject: {},
  data() {
    return {
      title: '项目进度',
      visible: false,
      url: {
        queryById: '/pm/pmProject/queryById',
        document: '/pm/pmProject/document'
      }
    }
  },
  mounted() {

  },
  props: {
    selectedKeys: {
      type: [Array, String]
    }
  },
  watch: {
    selectedKeys: {
      immediate: true,
      handler(val) {
        if (val.length > 0) {
          this.getById(val.toString())
        }
      }
    }
  },
  methods: {
    getById(id) {
      let projectId = id
      getAction(this.url.document, { projectId }).then(res => {
        if (res.success) {
          console.log(res.result)
          this.renderDocument(res.result)
        }
      })
    },
    renderDocument(item) {
      // -------------------------------↓↓↓↓↓↓↓↓↓↓↓前方高能↓↓↓↓↓↓↓↓↓↓↓↓-----------------------------------
      let myChart = this.$echarts.init(document.getElementById('project-plan-document'))
      let projectData = {
        projectName: item.project.name,
        startDate: item.project.planStartTime,
        endDate: item.project.planEndTime,
        // status: item.projectState,
        projectProperty: item.projectProperty,
        projectCycle: item.projectCycle,
        subjectList: item.subject.map(
          (item) => ({
            ...item,
            subjectId: item.subjectId,
            subjectName: item.subjectName,
            startDate: item.playStartTime,
            endDate: item.playEndTime,
            status: item.subjectState,
            targetList: item.targets.map((a => ({
              ...a,
              targetName: a.targetName,
              startDate: a.startTime,
              endDate: a.endTime
            })))
          })),
        //这个是什么数据 暂时没用到
        projectMilestoneList: [
          {
            name: '开工',
            code: '7',
            deadline: '2022-03-15',
            milestoneRate: 0
          },
          {
            name: '出±0',
            code: '1',
            deadline: '2022-04-15',
            milestoneRate: 0.0702
          },
          {
            name: '主体结构完成',
            code: '2',
            deadline: '2022-05-15',
            milestoneRate: 0
          }
        ]
      }
      let subjectList = projectData.subjectList.map(
        (item) => ({
          ...item,
          _type: 'engineering',
          _id: item.subjectId,
          _name: item.subjectName,
          _isExpanded: false,
          targetList: item.targetList.map((tar) => ({
            ...tar,
            _type: 'process',
            _id: tar.targetId,
            _parentId: tar.subjectId,
            _name: tar.targetName,
            _isExpanded: false
          }))
        })
      )
      let projectMilestoneList = [
        ...projectData.projectMilestoneList.map((item) => ({
          name: item.name,
          xAxis: new Date(item.deadline).getTime()
        })),
        {
          name: '今日',
          xAxis: new Date().getTime()
        }
      ]

// 记住datazoom的x轴偏移量
      let dataZoomStart = 0
      let valueSpanIndex = 5

      let renderChart = (start) => {
        // dataZoom
        let dayTimestamp = 24 * 60 * 60 * 1000
        // 全屏时手势更改的时间范围
        let VALUE_SPAN_ARRAY = Array.from(
          { length: 6 },
          (_, i) => (dayTimestamp * 30 * 6.5) / Math.pow(2, 5 - i)
        )
        let dataZoomX = [
          {
            type: 'slider',
            show: false,
            filterMode: 'none', // 不过滤数据，只改变数轴范围。
            xAxisIndex: [0, 1],
            start,
            // end: 100,
            // 坐标轴上最大和最小间隔相同 保证固定展示数量 且.5带来可滑动的观感
            minValueSpan: VALUE_SPAN_ARRAY[valueSpanIndex],
            maxValueSpan: VALUE_SPAN_ARRAY[valueSpanIndex]
          },
          {
            id: 'zoomX',
            type: 'inside',
            filterMode: 'none',
            xAxisIndex: [0, 1],
            zoomLock: true,
            preventDefaultMouseMove: false
          }
        ]
        let dataZoomY = [
          {
            type: 'slider',
            show: false,
            filterMode: 'none', // 不过滤数据，只改变数轴范围。
            yAxisIndex: 0,
            // 全屏时Y轴可以滑动
            minValueSpan: window.innerHeight / 80,
            maxValueSpan: window.innerHeight / 80
          },
          {
            type: 'inside',
            filterMode: 'none',
            yAxisIndex: 0,
            zoomLock: true,
            // 全屏时Y轴可以滑动
            moveOnMouseMove: true,
            preventDefaultMouseMove: true
          }
        ]
        let dataZoom = [...dataZoomX, ...dataZoomY]

        // grid
        let FULLSCREEN_GRID_LEFT = 210
        // 为了全屏时左侧设置背景色 将左右两侧方向设置0
        let grid = {
          top: 6,
          right: 0,
          bottom: 0,
          left: FULLSCREEN_GRID_LEFT,
          containLabel: true
        }

        // xAxis
        let xAxisMin = new Date(
          new Date(projectData.startDate).setDate(1)
        ).getTime() // 当月1号
        let xAxisBase = {
          type: 'time',
          position: 'top',
          min: xAxisMin,
          axisLabel: {
            margin: 6,
            formatter: '{yyyy}.{MM}.{dd}',
            color: '#6F6F6F',
            fontSize: 10,
            align: 'left'
          },
          axisLine: {
            show: false
          },
          axisTick: {
            show: false
          },
          splitArea: {
            show: false
          }
        }
        let xAxis = [
          {
            ...xAxisBase,
            minInterval: dayTimestamp * 7,
            // maxInterval: dayTimestamp * 7,
            // splitNumber: 3,
            axisLabel: {
              show: true,
              margin: 12,
              // formatter: '{yyyy}.{MM}',
              formatter() {
                return valueSpanIndex >= 5 ? '{yyyy}.{MM}' : '{yyyy}.{MM}.{dd}'
              },
              hideOverlap: true, // 避免重叠
              color: '#848484',
              fontSize: 10,
              align: 'left'
            },
            axisLine: {
              show: true,
              lineStyle: {
                color: '#DCDFE7',
                width: 18,
                cap: 'butt'
              }
            }
          },
          {
            ...xAxisBase,
            offset: 28,
            // 时间区间较小时(valueSpanIndex <= 3) 直接赋值splitNumber最小 避免展示过多 这里最好还是把季度去掉 没有任何意义
            minInterval: valueSpanIndex > 3 ? dayTimestamp * 30 * 4 : undefined,
            maxInterval: valueSpanIndex > 3 ? dayTimestamp * 30 * 4 : undefined,
            splitNumber: valueSpanIndex <= 3 && 1,
            axisLabel: {
              margin: 4,
              // echarts自带季度有bug
              // formatter: 'Q{Q}',
              formatter(value) {
                let month = new Date(value).getMonth()
                if (month < 3) {
                  return '第一季度'
                } else if (month < 6) {
                  return '第二季度'
                } else if (month < 9) {
                  return '第三季度'
                } else {
                  return '第四季度'
                }
              },
              // showMinLabel: false,
              // showMaxLabel: false,
              color: '#848484',
              fontSize: 12,
              align: 'left'
            },
            axisLine: {
              show: true,
              lineStyle: {
                color: '#EAEAEA',
                width: 0.5
              }
            }
          }
        ]

        // yAxis
        let yAxis = {
          // 这里设置false会影响splitArea展示
          // show: false,
          // 这行data去掉滑动就很顺畅 通过min & max参数定义Y轴
          // data: subjectList.value.map((item) => item._name),
          inverse: true,
          interval: 1,
          axisLabel: {
            show: false
          },
          axisLine: {
            show: false
          },
          axisTick: {
            show: false
          },
          splitLine: {
            show: false
          },
          splitArea: {
            show: true,
            areaStyle: {
              color: subjectList.map((item) => {
                if (item._type === 'engineering' && !item._isExpanded) {
                  return 'white'
                } else {
                  return item.status === '1' ? '#FFEEEE' : '#EBF3FE'
                }
              })
            }
          },
          min: 0,
          max: subjectList.length
        }

        // series
        const STATUS_MAP = ['未开始', '执行中', '已关闭', '已延期']
        let renderCircleItem = (isShowCircle, isExpanded, status) => {
          return {
            type: 'circle',
            z2: 3,
            textContent: {
              style: {
                y: -1.6,
                text: isExpanded ? '-' : '+',
                //点击展开的小+-颜色
                textFill: status==='0'?'#3688F6':status==='1'?'#fa8c16':status==='2'?'#52c41a':'#f5222d',
                fontSize: '16px'
              }
            },
            textConfig: {
              position: 'inside'
            },
            shape: {
              // cx: 0,
              // cy: 0,
              r: 8
            },
            style: {
              fill: status === '0' ? '#FFEEEE' : '#EBF3FE'
              // fill: status==='0'?'#3688F6':status==='1'?'#fa8c16':status==='2'?'#52c41a':'#f5222d',
            },
            ignore: !isShowCircle
          }
        }
        let renderGanttItem = (params, api) => {
          let yIndex = params.dataIndexInside // y轴数据index值
          let {
            _type,
            _name,
            _isExpanded,
            projectCycle: projectCycle,
            status,
            targetList
          } = subjectList[yIndex]
          let isShowCircle = _type === 'engineering' && !!targetList.length
          let startDate = api.coord([api.value(0), yIndex]) // 开始时间数值转换成坐标系上的点
          let endDate = api.coord([api.value(1), yIndex]) // 结束时间数值转换成坐标系上的点
          let barLength = endDate[0] - startDate[0] // 长度
          let yIntervalHeight = api.size([0, 1])[1] // y轴间隔距离，单位为1应得到的长度；x轴为0得到0略过
          let barHeight = yIntervalHeight * (_type === 'engineering' ? 0.48 : 0.24) // 柱状图高度由y轴间隔高度乘以系数得到
          let [x, y] = startDate
          let text = `${projectCycle || 0}% (${STATUS_MAP[status]})`
          let textWidth = text.length * 11 + (isShowCircle ? 24 : 4) // 计算path的长度 这里无法找到方法自适应 within my capacity oops~

          return {
            type: 'group',
            id: 'ganttItem',
            position: [x, y + (yIntervalHeight - barHeight) / 2],
            children: [
              {
                type: 'rect',
                textContent: {
                  style: {
                    text,
                    textFill: '#323232'
                  },
                  ignore: _type === 'process'
                },
                textConfig: {
                  position: 'insideLeft'
                },
                shape: {
                  width: barLength,
                  height: barHeight,
                  r: 3 // 设置圆角矩形
                },
                style: {
                  fill:
                        status === '0'
                          ? _type === 'engineering'
                          ? '#3688F6'
                          : '#9AC3FA'
                            :
                         status === '1'
                           ? _type === 'engineering'
                           ? '#fa8c16'
                           : '#ffd591'
                             :
                         status === '2'
                           ? _type === 'engineering'
                           ? '#52c41a'
                           : '#b7eb8f'
                        : _type === 'engineering'
                           ? '#f5222d'
                           : '#FFA8A8'
                }

              },
              {
                type: 'rect',
                shape: {
                  width: (barLength * projectCycle) / 100,
                  height: barHeight / 3,
                  r: 3 // 设置圆角矩形
                },
                style: {
                  // fill: status === '2' ? '#E64A4A' : '#006CCF'
                  fill:   status==='0'?'#3688F6':status==='1'?'#fa8c16':status==='2'?'#52c41a':'#f5222d'

                },
                ignore: !projectCycle // 非全屏时展示; 全屏且勾选实际进度明细时展示;
              }
            ]
          }
        }
        let renderAxisLabelItem = (params, api) => {
          let yIndex = params.dataIndexInside // y轴数据index值
          let { _type, _name, _isExpanded, status, targetList } = subjectList[yIndex]
          let isShowCircle = _type === 'engineering' && !!targetList.length
          let y = api.coord([0, api.value(0)])[1]
          let AXIS_LABEL_LEFT = 24
          let AXIS_LABEL_RIGHT = 6
          let AXIS_LABEL_HEIGHT = api.size([0, 1])[1] * 0.8

          // 裁掉超出y轴坐标系的部分
          if (y < params.coordSys.y - AXIS_LABEL_HEIGHT) {
            return
          }
          return {
            type: 'group',
            position: [
              AXIS_LABEL_LEFT,
              y + AXIS_LABEL_HEIGHT / 8 /* 高度占比0.8 居中上下各留0.1 所以除以8 */
            ],
            children: [
              _type === 'engineering'
                ? {
                  type: 'rect',
                  z2: 1,
                  shape: {
                    width:
                      FULLSCREEN_GRID_LEFT - AXIS_LABEL_LEFT - AXIS_LABEL_RIGHT,
                    height: AXIS_LABEL_HEIGHT,
                    r: 3
                  },
                  style: {
                    fill: 'white'
                  }
                }
                : {
                  type: 'group',
                  children: [
                    {
                      type: 'polyline',
                      shape: {
                        points: [
                          [10, -48],
                          [10, AXIS_LABEL_HEIGHT / 2],
                          [16, AXIS_LABEL_HEIGHT / 2]
                        ]
                      },
                      style: {
                        fill: 'transparent',
                        stroke: '#D6D6D6'
                      }
                    },
                    {
                      type: 'circle',
                      shape: {
                        cx: 20,
                        cy: AXIS_LABEL_HEIGHT / 2,
                        r: 2
                      },
                      style: {
                        // fill: status === '0' ? '#FF5252' : '#3688F6'
                        fill:   status==='0'?'#3688F6':status==='1'?'#fa8c16':status==='2'?'#52c41a':'#f5222d'
                      }
                    }
                  ]
                },
              {
                type: 'group',
                position: [12, AXIS_LABEL_HEIGHT / 2],
                children: [
                  renderCircleItem(isShowCircle, _isExpanded, status),
                  {
                    type: 'text',
                    z2: 3,
                    style: {
                      x: _type === 'engineering' ? 12 : 16,
                      y: -6,
                      text: _name,
                      textFill: _type === 'engineering' ? '#323232' : '#5B5B5B',
                      fontWeight: _type === 'engineering' && 'bold'
                    }
                  }
                ]
              },
              {
                type: 'text',
                z2: 5,
                style: {
                  x: FULLSCREEN_GRID_LEFT - AXIS_LABEL_LEFT - AXIS_LABEL_RIGHT - 12,
                  y: AXIS_LABEL_HEIGHT / 2 - 8,
                  text: '>',
                  textFill: '#D6D6D6'
                }
              }
            ]
          }
        }
        let markLine = {
          symbol: ['emptyCircle'],
          animation: false,
          data: projectMilestoneList.map((item) => ({
            ...item,
            y: 40,
            label: {
              show: false,
              silent: true, // 不响应和触发鼠标事件
              position: 'start'
            },
            lineStyle: {
              color: '#F2BA40',
              opacity: 0.5
            },
            emphasis: {
              label: {
                show: true,
                opacity: 1,
                formatter(params) {
                  return (
                    `{a|${params.name}}` +
                    '\n' +
                    `{b|${new Date(params.value).getMonth() + 1}.${new Date(
                      params.value
                    ).getDate()}}`
                  )
                },
                rich: {
                  a: {
                    color: '#464646',
                    fontSize: 16
                  },
                  b: {
                    color: '#999',
                    fontSize: 10,
                    padding: [2, 0, 2, 0]
                  }
                }
              },
              lineStyle: {
                color: '#205294'
              }
            }
          }))
        }
        let seriesBase = {
          type: 'custom',
          clip: true, // 裁掉所有超出坐标系的部分
          // custom can only use Array but not Object data format!
          // dimensions: 0 startDate 1 endDate
          data: subjectList.map((item) => [
            new Date(item.startDate).getTime(),
            new Date(item.endDate).getTime()
          ]),
          renderItem: renderGanttItem,
          xAxisIndex: 0,
          encode: {
            // 不可删 对应zoomdata
            x: [0, 1],
            y: 0
          },
          markLine
        }
        let series = [
          {
            ...seriesBase,
            markLine: {
              ...markLine,
              data: markLine.data.map((item) => ({
                ...item,
                y: 44,
                emphasis: {
                  label: {
                    show: false
                  }
                }
              }))
            }
          },
          // just for xAxis Q1-4
          {
            type: 'custom',
            data: subjectList.map((item) => [
              new Date(item.startDate).getTime(),
              new Date(item.endDate).getTime()
            ]),
            renderItem: () => {
              return null
            },
            xAxisIndex: 1,
            encode: {
              x: [0, 1],
              y: 0
            }
          },
          {
            type: 'custom',
            data: subjectList.map((_, index) => [index]),
            renderItem: renderAxisLabelItem,
            encode: {
              x: -1,
              y: 0
            }
          }
        ]

        myChart.setOption({
          dataZoom,
          grid,
          xAxis,
          yAxis,
          series,
          backgroundColor: '#F8F9FB'
        })
      }
      let resizeChart = () => {
        setTimeout(() => {
          myChart.resize({ height: window.innerHeight })
        })
      }

      renderChart()
      resizeChart()

      myChart.on('click', 'series.custom', (event) => {
        // 仅工程工序项
        if (event.componentSubType !== 'custom') return
        let index = event.dataIndex
        let selectedItem = subjectList[index]
        if (selectedItem._type === 'engineering') {
          // 工程下无工序情况
          if (!selectedItem.targetList.length) return

          if (selectedItem._isExpanded) {
            subjectList = subjectList.filter(
              (item) => item.subjectId !== selectedItem.subjectId
            )
          } else {
            subjectList.splice(
              index + 1,
              0,
              ...selectedItem.targetList
            )
          }
          subjectList[index]._isExpanded = !subjectList[index]._isExpanded
          renderChart(dataZoomStart)
          resizeChart()
        } else {
          emit('clickProcess', selectedItem)
        }
      })
      myChart.on('dataZoom', (event) => {
        if (!event.batch) return
        dataZoomStart = event.batch[0].start
      })

    }
  }
}
</script>

<style scoped lang='less'>


</style>